﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using Citi.GenericApplications.SchedulerUi.EmailSenderWcf;
using Citi.RoutineBase;

namespace Citi.GenericApplications.SchedulerUi
{
    public class EmailReportFinished : IExecutableRoutine
    {
        private string file;

        public IEnumerable<RoutineParameter> Parameters
        {
            get
            {
                return new List<RoutineParameter> { 
                    new RoutineParameter{ Description = "Report Folder", Name ="ReportFolder", Nullable= false, Required = true, Type = typeof(string)},
                    new RoutineParameter{ Description = "Report Name Pattern", Name ="ReportPattern", Nullable= false, Required = true, Type = typeof(string)},
                    new RoutineParameter{ Description = "Report extension", Name ="ReportExtension", Nullable= false, Required = true, Type = typeof(string)},
                    new RoutineParameter{ Description = "Friendly Report Name", Name ="FriendlyReportName", Nullable = false, Required = true, Type = typeof(string)},
                    new RoutineParameter{ Description = "Email to send when some error occurs. Separated by Semicolons(;).", Name ="EmailAddressError", Nullable= false, Required = true, Type = typeof(string)},
                    new RoutineParameter{ Description = "Users that must receive email when the reports are available. Separated by Semicolons(;).", Name ="EmailAddressUsers", Nullable = false, Required = true, Type = typeof(string)}
                };
            }
        }

        public void Rollback(ref ICurrentAction currentAction, Dictionary<string, object> parameters)
        {

        }

        public void Start(DateTime scheduledDate, ref ICurrentAction currentAction, Dictionary<string, object> parameters)
        {
            var templateId = int.Parse(ConfigurationManager.AppSettings["EmailReportFinishedTemplateId"]);
            var reportFolder = parameters["ReportFolder"].ToString();
            var reportPattern = parameters["ReportPattern"].ToString();
            var reportExtension = parameters["ReportExtension"].ToString();
            var friendlyReportName = parameters["FriendlyReportName"].ToString();
            var robotUsername = parameters["RobotUsername"].ToString();
            var robotPassword = parameters["RobotPassword"].ToString();
            var emailAddressUsers = parameters["EmailAddressUsers"].ToString().Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            var emailAddressError = parameters["EmailAddressError"].ToString().Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();

            if (ValidateFiles(reportFolder, reportExtension, reportPattern, friendlyReportName, emailAddressError, robotUsername, robotPassword, ref currentAction))
            {
                using (var client = new EmailClient())
                {
                    var email = new EmailSenderWcf.Email
                    {
                        TemplateId = templateId,
                        Importance = EnumsEmailImportance.Normal,
                        To = emailAddressUsers.Select(x => new EmailSenderWcf.EmailAddress { Description = x }).ToList(),
                        Parameters = new Dictionary<string, string> 
                        { 
                            { "[ReportName]", friendlyReportName}, 
                            { "[FileName]", Path.GetFileName(file)},
                            { "[SharePath]", reportFolder},
                            { "[TimeStamp]", File.GetLastWriteTime(file).ToString("dd/MM/yyyy HH:mm") },
                        }
                    };

                    client.InsertEmailInQueue(email);
                }
            }
        }

        private string GetValidationMessage(string reportFolder, string reportPath)
        {
            var message = string.Format("Path: {0}", string.Concat(reportPath, " {0}"));

            if(!Directory.Exists(reportFolder))
                return string.Format(message, "doesn't exist");
            if (!File.Exists(reportPath))
                return string.Format(message, "File doesn't exist");
            if (File.GetLastWriteTime(reportPath).Date != DateTime.Today)
                return string.Format(message, string.Format("File is out of date. Last Update: {0}", File.GetLastWriteTime(reportPath).Date));
            else
                return string.Format(message, "File OK");
        }

        public bool ValidateFiles(string reportFolder, string reportExtension, string reportPattern, string friendlyReportName, List<string> emailAddressError, string username, string password, ref ICurrentAction currentAction)
        {
            currentAction.Description = "Validating file";

            if (!reportExtension.StartsWith("."))
                reportExtension = string.Concat(".", reportExtension);

            var notValid = !Directory.Exists(reportFolder);

            if (!notValid)
            {
                file = Directory.GetFiles(reportFolder)
                       .Where(x => Path.GetFileNameWithoutExtension(x).ToUpper().StartsWith(reportPattern.ToUpper())
                           && Path.GetExtension(x).ToUpper() == reportExtension.ToUpper()
                           && File.GetLastWriteTime(x).Date == DateTime.Today)
                           .OrderByDescending(x => File.GetLastWriteTime(x)).FirstOrDefault();

                notValid = file == null;
            }

            if (notValid)
            {
                var validationMessage = GetValidationMessage(reportFolder, file);

                currentAction.Description = "Validation failed. An error email will be sent.";
                currentAction.Description = validationMessage;

                using (var client = new EmailClient())
                {
                    var email = new EmailSenderWcf.Email
                    {
                        BodyMessage = string.Format("An error ocurred when this routine tried to send {0} email<br/><br/> {1}",
                            friendlyReportName, validationMessage),
                        Subject = string.Format("{0} Error", friendlyReportName),
                        SentOnBehalfOfName = "O&T Finance Comunica",
                        To = emailAddressError.Select(x => new EmailSenderWcf.EmailAddress { Description = x }).ToList(),
                        ApplicationName = "General Automations",
                        Parameters = new Dictionary<string, string>(),
                        Importance = EnumsEmailImportance.High
                    };

                    client.InsertEmailInQueue(email);
                    currentAction.Description = "Email sent.";
                }

                return false;
            }

            currentAction.Description = "Validation is OK";
            return true;
        }

        public void Stop(ref ICurrentAction currentAction, Dictionary<string, object> parameters)
        {

        }
    }
}
